#include "Controller.h"
#include "ui_Controller.h"

Controller::Controller(QString id,QWebSocket* socket,QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Controller)
    ,m_id(id)
    ,m_socket(socket)
{
    ui->setupUi(this);
    initUI();
    initSQLiteDB();// 初始化本地数据库
    askForMyInfo();// 向服务器申请我的个人信息（并开始一系列的初始化操作）

    connect(m_socket,&QWebSocket::disconnected,this,&Controller::onDisconnected);
    connect(m_socket,&QWebSocket::textMessageReceived,this,&Controller::onTextMessageReceived);
    connect(this,&Controller::deleteAFriend,this,&Controller::onDeleteAFriend);
    connect(ui->msgTextEdit,&MyTextEdit::keyForSendMsg,[this](){
        ui->sendBtn->click();
    });
    connect(ui->chatListView,&ChatListView::menuChoice,this,&Controller::onMenuChoice);
}

Controller::~Controller()
{
    delete ui;
}

void Controller::initUI()
{
    // 主窗体的大小
    setFixedSize(890,600);

    // 设置按钮的图标的合适大小
    ui->chatBtn->setIconSize(QSize(35,35));
    ui->chatBtn->setStyleSheet("border: 0px;");
    ui->friendBtn->setIconSize(QSize(37,37));
    ui->friendBtn->setStyleSheet("border: 0px;");
    ui->meBtn->setIconSize(QSize(37,37));
    ui->meBtn->setStyleSheet("border: 0px;");
    ui->settingBtn->setIconSize(QSize(35,35));
    ui->settingBtn->setStyleSheet("border: 0px;");

    // 选中聊天按钮
    changeButtonImage(ui->chatBtn);

    // 初始化名字标签
    ui->nameChatLabel->setText("");
    ui->nameFriendLabel->setText("");

    // 设置好友页面的ListView相关
    m_friendModel = new QStandardItemModel(this);// 实例化模型
    FriendItemDelegate* friendDelegate = new FriendItemDelegate(this);// 实例化绘制类
    ui->friendListView->setModel(m_friendModel);// 装载模型
    ui->friendListView->setItemDelegate(friendDelegate);// 装载绘制类
    ui->friendListView->setUniformItemSizes(true); // 统一项大小
    ui->friendListView->setResizeMode(QListView::Adjust); // 自动调整布局

    ui->friendInfoStackedWidget->setCurrentIndex(0);// 初始显示空白页

    // 连接ListView项变化的信号和槽函数
    connect(ui->friendListView->selectionModel(),&QItemSelectionModel::currentChanged,this,&Controller::onFriendListViewIndexChange);

    // 添加好友申请项
    QPixmap pixmap(":/images/conrtroler/friendItem.png");
    m_friendItem = new QStandardItem();
    m_friendItem->setData(pixmap,Qt::UserRole + 1);
    m_friendItem->setData("好友申请",Qt::UserRole + 2);
    m_friendItem->setData(false,Qt::UserRole + 3);
    m_friendItem->setData("friendRequestItem",Qt::UserRole + 4);// 项的名称
    m_friendModel->appendRow(m_friendItem);

    // 设置聊天页面的ListView相关
    m_chatModel = new QStandardItemModel(this);
    ui->chatListView->setModel(m_chatModel);
    ChatItemDelegate* chatDelegate = new ChatItemDelegate(this);
    ui->chatListView->setItemDelegate(chatDelegate);
    ui->chatListView->setUniformItemSizes(true); // 统一项大小
    ui->chatListView->setResizeMode(QListView::Adjust); // 自动调整布局
    connect(ui->chatListView->selectionModel(),&QItemSelectionModel::currentChanged,this,&Controller::onChatListViewIndexChange);
}

void Controller::initSQLiteDB()
{
    QString name = m_id + ".db";
    QString connectionName = m_id + "SQLite";

    // 创建轻量级数据库（不存在则自动创建）
    m_db = QSqlDatabase::addDatabase("QSQLITE",  connectionName);
    m_db.setDatabaseName(name);
    if(!m_db.open()){
        qDebug()<<"无法打开创建的本地轻量级QSQLite数据库"<<m_db.lastError();
        return;
    }

    QSqlQuery query(m_db);

    // 创建聊天项表ChatItem(count, friend_id, lastMsg, timestamp)
    query.prepare("CREATE TABLE IF NOT EXISTS ChatItem("
                  "count INTEGER PRIMARY KEY AUTOINCREMENT,"
                  "friend_id VARCHAR(255),"
                  "lastMsg LONGTEXT,"
                  "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,"
                  "UNIQUE(friend_id)"
                  ")");
    if(!query.exec()){
        qDebug()<<"创建聊天项表的sql语句执行失败"<<query.lastError();
        return;
    }

    // 创建聊天记录表ChatData(count, friend_id, senderOrreceiver, content, type, filename, timestamp)
    query.prepare("CREATE TABLE IF NOT EXISTS ChatData("
                  "count INTEGER PRIMARY KEY AUTOINCREMENT,"
                  "friend_id VARCHAR(255),"
                  "senderOrreceiver VARCHAR(255),"
                  "content LONGTEXT,"
                  "type VARCHAR(255),"
                  "filename VARCHAR(255),"
                  "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP"
                  ")");
    if(!query.exec()){
        qDebug()<<"创建聊天记录表的sql语句执行失败"<<query.lastError();
    }
}



void Controller::sendJsonToServer(QJsonObject &jsonObj)
{
    jsonObj["end"] = "end";
    QJsonDocument jsonDoc(jsonObj);
    QByteArray jsonData = jsonDoc.toJson();
    QString jsonStr = QString::fromUtf8(jsonData);
    m_socket->sendTextMessage(jsonStr);
    m_socket->flush();
}

void Controller::changeButtonImage(QPushButton *curBtn)
{
    // 重置所有按钮为未选中的图片
    ui->chatBtn->setIcon(QIcon(":/images/conrtroler/message1.png"));
    ui->friendBtn->setIcon(QIcon(":/images/conrtroler/friend1.png"));
    ui->meBtn->setIcon(QIcon(":/images/conrtroler/me1.png"));
    ui->settingBtn->setIcon(QIcon(":/images/conrtroler/set1.png"));

    if(curBtn == ui->chatBtn){
        ui->chatBtn->setIcon(QIcon(":/images/conrtroler/message2.png"));
        ui->stackedWidget->setCurrentIndex(0);
    }else if(curBtn == ui->friendBtn){
        ui->friendBtn->setIcon(QIcon(":/images/conrtroler/friend2.png"));
        ui->stackedWidget->setCurrentIndex(1);
    }else if(curBtn == ui->meBtn){
        ui->meBtn->setIcon(QIcon(":/images/conrtroler/me2.png"));
        ui->stackedWidget->setCurrentIndex(2);
    }else if(curBtn == ui->settingBtn){
        ui->settingBtn->setIcon(QIcon(":/images/conrtroler/set2.png"));
        ui->stackedWidget->setCurrentIndex(3);
    }
}

void Controller::askForMyInfo()
{
    QJsonObject jsonObj;
    jsonObj["tag"] = "myInfo";
    sendJsonToServer(jsonObj);
}

void Controller::askForMyFriendInfo()
{
    QJsonObject jsonObj;
    jsonObj["tag"] = "friendInfo";
    sendJsonToServer(jsonObj);
}

void Controller::askForMyFriendRequestList()
{
    QJsonObject jsonObj;
    jsonObj["tag"] = "friendRequestList";
    sendJsonToServer(jsonObj);
}

void Controller::askForMyUnReadMsg()
{
    QJsonObject jsonObj;
    jsonObj["tag"] = "myUnReadMsg";
    sendJsonToServer(jsonObj);
}

void Controller::initChatData()
{
    // 根据好友列表，查询出聊天记录信息
    QSqlQuery query(m_db);
    query.prepare("select * from ChatData where friend_id = :friend_id order by timestamp ASC");
    // 聊天记录表ChatData(count, friend_id, senderOrreceiver, content, type, filename, timestamp)
    for(Info& info : m_friendMap){
        query.bindValue(":friend_id", info.id);
        QWidget* page = ui->chatStackedWidget->findChild<QWidget*>(info.id);
        if(!query.exec() || !page){
            qDebug()<<"初始时通过本地数据库查找聊天记录sql语句执行失败或页面无法获取"<<query.lastError();
            continue;
        }
        while (query.next()) {
            // 区分类型
            MsgType type;
            if(query.value("type").toString() == "textType"){
                type = MsgType::text;
            }else if(query.value("type").toString() == "photoType"){
                type = MsgType::photo;
            }else{
                type = MsgType::file;
            }

            QString text = query.value("content").toString();
            QString filename = query.value("filename").toString();

            // 按发送者进行分别处理
            if(query.value("senderOrreceiver").toString() == "sender"){
                addAMsgIntoPage(page,type,m_id,text,true,filename);
            }
            else if(query.value("senderOrreceiver").toString() == "receiver"){
                addAMsgIntoPage(page,type,info.id,text,true,filename);
            }
            // 否则是时间标签（跟随天数递增逻辑待实现）
            else{
                QListWidget* listWidget = page->findChild<QListWidget*>();
                if(listWidget){
                    QDateTime time = QDateTime::fromString(text,"yyyy-MM-dd HH:mm:ss");
                    addATimeLabel(listWidget,time);
                }
            }
        }
    }
}

void Controller::initChatItem()
{
    // 通过本地数据库，添加聊天项信息
    // 聊天项表ChatItem(count, friend_id, lastMsg, timestamp)
    QSqlQuery query(m_db);
    query.prepare("select * from ChatItem order by timestamp ASC");
    if(!query.exec()){
        qDebug()<<"初始化时，从本地获取聊天项的sql语句执行失败"<<query.lastError();
        return;
    }

    while (query.next()) {
        QMap<QString, Info>::iterator it = m_friendMap.find(query.value("friend_id").toString());
        if(it == m_friendMap.end()){
            continue;
        }
        Info friendInfo = it.value();

        QStandardItem* item = new QStandardItem();
        item->setData(friendInfo.avatarPixmap,Qt::UserRole + 1);// 添加头像
        item->setData(friendInfo.nickname,Qt::UserRole + 2);// 添加昵称
        item->setData(false,Qt::UserRole + 3);// 添加未读标志
        item->setData(friendInfo.id,Qt::UserRole + 4);// 添加账号信息
        item->setData(query.value("lastMsg").toString(),Qt::UserRole + 5);// 添加上一次聊天信息
        m_chatModel->appendRow(item);
    }
}

void Controller::setMyPageEnable(bool flag)
{
    ui->idLineEdit->setEnabled(false);// 账号不允许更改
    ui->pwdLineEdit->setEnabled(flag);
    ui->nicknameLineEdit->setEnabled(flag);
    ui->nanRadioButton->setEnabled(flag);
    ui->nvRadioButton->setEnabled(flag);
    ui->signaturePlainTextEdit->setEnabled(flag);
    ui->questionTextEdit->setEnabled(flag);
    ui->answerTextEdit->setEnabled(flag);
}

QPixmap Controller::byteArrayToPixmap(QString avatarStr)
{
    QPixmap pix(":/images/login/defult_avatar.png");
    if(avatarStr.isEmpty()){
        return pix;
    }
    QByteArray avatarData = QByteArray::fromBase64(avatarStr.toUtf8());
    QImage image = QImage::fromData(avatarData);
    if(image.isNull()){
        qDebug()<<"头像数据转换失败，改为使用默认头像";
    }else{
        pix = QPixmap::fromImage(image);
    }
    return pix;
}

void Controller::addAChatItem(Info friendInfo, bool unread, QString lastMsg)
{
    QStandardItem* item = new QStandardItem();
    item->setData(friendInfo.avatarPixmap,Qt::UserRole + 1);// 添加头像
    item->setData(friendInfo.nickname,Qt::UserRole + 2);// 添加昵称
    item->setData(unread,Qt::UserRole + 3);// 添加未读标志
    item->setData(friendInfo.id,Qt::UserRole + 4);// 添加账号信息
    item->setData(lastMsg,Qt::UserRole + 5);// 添加上一次聊天信息
    m_chatModel->appendRow(item);

    // 添加到本地数据库
    // 聊天项表ChatItem(count, friend_id, lastMsg, timestamp)
    QSqlQuery query(m_db);
    query.prepare("insert into ChatItem(friend_id, lastMsg) values(:friend_id, :lastMsg)");
    query.bindValue(":friend_id", friendInfo.id);
    query.bindValue(":lastMsg", "");
    if(!query.exec()){
        qDebug()<<"在创建一个好友项时，将该项存入本地数据库的sql语句执行失败"<<query.lastError();
    }

    // 添加一个聊天页面
    addAChatPage(friendInfo.id);
}

void Controller::addAChatPage(QString id)
{
    // 判断是否已经存在聊天页面了
    QWidget* oldPage = ui->chatStackedWidget->findChild<QWidget*>(id);
    if(oldPage){
        return;// 存在了就返回
    }

    // 添加一个聊天页面(聊天页面是一个QListWdget类型，以便显示一条条的聊天信息)
    QWidget *newPage = new QWidget();
    newPage->setObjectName(id);// 页面的objectname是id

    QListWidget* listWidget = new QListWidget(newPage);
    // 将列表名为上一次的时间字符串
    QDateTime lastTime = QDateTime::fromString("2001-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss");
    QString timeString = lastTime.toString("yyyy-MM-dd HH:mm:ss");

    listWidget->setObjectName(timeString);
    listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);// 设置为无水平滚动
    listWidget->setSelectionMode(QAbstractItemView::NoSelection);
    // 禁用悬浮时背景色变化
    listWidget->setStyleSheet("QListWidget::item:hover { background-color: transparent; }");

    // 设置成按像素滚动(每次10像素)
    QScrollBar* verticalScrollBar = listWidget->verticalScrollBar();
    verticalScrollBar->setSingleStep(10);

    QVBoxLayout *layout = new QVBoxLayout(newPage);
    layout->addWidget(listWidget);
    newPage->setLayout(layout);

    ui->chatStackedWidget->addWidget(newPage);
}

void Controller::addAFriendItem(Info friendInfo)
{
    QStandardItem* item = new QStandardItem();
    item->setData(friendInfo.avatarPixmap,Qt::UserRole + 1);// 添加头像
    item->setData(friendInfo.nickname,Qt::UserRole + 2);// 添加昵称
    item->setData(friendInfo.id,Qt::UserRole + 4);// 添加项名称
    m_friendModel->appendRow(item);

    // 创建这个好友的好友页面
    addAFriendPage(friendInfo);
}

void Controller::addAFriendPage(Info friendInfo)
{
    // 如果已经存在，则将其删除
    QWidget* page = ui->friendInfoStackedWidget->findChild<QWidget*>(friendInfo.id);
    if(page){
        ui->friendInfoStackedWidget->removeWidget(page);
        page->deleteLater();
    }

    QWidget *newPage = new QWidget();
    newPage->setObjectName(friendInfo.id);
    QVBoxLayout* layout = new QVBoxLayout();

    // 处理第一行的头像显示
    QLabel *avatarLabel = new QLabel();
    avatarLabel->setFixedSize(100,100);
    avatarLabel->setPixmap(friendInfo.avatarPixmap.scaled(100,100,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));
    layout->addWidget(avatarLabel,0,Qt::AlignCenter);

    // C++新特性的匿名函数与绑定器
    auto addLabelToLayout = [&](const QString text){
        QLabel *label = new QLabel();
        label->setText(text);
        label->setAlignment(Qt::AlignCenter);
        layout->addWidget(label);
    };

    // 第二行的昵称显示/第三行的账号显示/第四行的性别显示/第五行的个性签名显示
    addLabelToLayout(friendInfo.nickname);
    addLabelToLayout(friendInfo.id);
    addLabelToLayout(friendInfo.gender);
    addLabelToLayout(friendInfo.signature);

    // 第六行发起聊天按钮和删除好友按钮
    QHBoxLayout* hLayout = new QHBoxLayout();

    QPushButton* chatBtn = new QPushButton();
    chatBtn->setText("发起聊天");
    chatBtn->setFixedSize(100,40);
    hLayout->addWidget(chatBtn, 0, Qt::AlignHCenter);

    QPushButton* deleteBtn = new QPushButton();
    deleteBtn->setText("删除好友");
    deleteBtn->setFixedSize(100,40);
    hLayout->addWidget(deleteBtn, 0, Qt::AlignHCenter);

    QWidget* hLayoutWidget = new QWidget();
    hLayoutWidget->setLayout(hLayout);
    layout->addWidget(hLayoutWidget);// 添加到总布局中

    newPage->setLayout(layout);
    ui->friendInfoStackedWidget->addWidget(newPage);

    // 处理连接按钮的信号槽
    connect(chatBtn,&QPushButton::clicked,[=](){
        bool find = false;
        // 查找对应的聊天项
        for(int row = 0; row < m_chatModel->rowCount(); row++){
            QModelIndex index = m_chatModel->index(row,0);
            // 寻找匹配的项并模拟点击
            if(index.data(Qt::UserRole + 4).toString() == friendInfo.id){
                // 清除并选中目标项
                ui->chatListView->setCurrentIndex(index);
                ui->chatListView->selectionModel()->select(index,QItemSelectionModel::ClearAndSelect);
                if(index.data(Qt::UserRole + 3).toBool() == true){
                    QStandardItem* item = m_chatModel->itemFromIndex(index);
                    item->setData(false, Qt::UserRole + 3);
                    m_chatModel->dataChanged(index,index,{Qt::UserRole + 3});
                }
                find = true;
                break;
            }
        }

        // 没有则创建一个聊天项（聊天页面一定有的）
        if(!find){
            addAChatItem(friendInfo,false,"");
        }

        // 再次尝试查找对应的聊天项
        for(int row = 0; row < m_chatModel->rowCount(); row++){
            QModelIndex index = m_chatModel->index(row,0);
            // 寻找匹配的项并模拟点击
            if(index.data(Qt::UserRole + 4).toString() == friendInfo.id){
                // 清除并选中目标项
                ui->chatListView->setCurrentIndex(index);
                ui->chatListView->selectionModel()->select(index,QItemSelectionModel::ClearAndSelect);
                if(index.data(Qt::UserRole + 3).toBool() == true){
                    QStandardItem* item = m_chatModel->itemFromIndex(index);
                    item->setData(false, Qt::UserRole + 3);
                    m_chatModel->dataChanged(index,index,{Qt::UserRole + 3});
                }
                find = true;
                break;
            }
        }

        // 转回到聊天页面表
        changeButtonImage(ui->chatBtn);
    });
    connect(deleteBtn,&QPushButton::clicked,[=](){
        emit deleteAFriend(friendInfo.id);// 发送删除某人的信号
    });
}

void Controller::liftSomeoneInChatView(QString id)
{
    QModelIndex index;
    bool found = false; // 标记是否找到匹配项
    // 遍历ui->chatListView中的项，检查是否Qt::UserRole + 4的值是否相等
    for(int row = 0; row < m_chatModel->rowCount(); row++){
        index = m_chatModel->index(row,0);
        // 寻找到匹配的项
        if(index.data(Qt::UserRole + 4).toString() == id){
            found = true;
            break;
        }
    }

    if(found && index.isValid()){
        // 进行移动操作
        QStandardItem* item = m_chatModel->itemFromIndex(index);
        if (item) {
            QStandardItem* clonedItem = item->clone();// 克隆，避免重复插入的警告
            m_chatModel->insertRow(0, clonedItem);// 插入到顶部
            m_chatModel->removeRow(index.row() + 1);// 移除
        }
    }
}

void Controller::addAMsgIntoPage(const QWidget *page, const MsgType type, const QString &sender, QString &content, bool isInit, QString filename)
{
    QString msgType = "textType";
    QString lastText = content;
    // 根据类型显示文本
    if(type == MsgType::photo){
        lastText = "[图片消息]";
        msgType = "photoType";
    }else if(type == MsgType::file){
        lastText = "[文件消息]";
        msgType = "fileType";
    }

    // 更新UserRole 5（上一次聊天记录）
    for(int row = 0; row < m_chatModel->rowCount(); row++){
        QModelIndex index = m_chatModel->index(row, 0);
        if(index.data(Qt::UserRole + 4) == page->objectName()){
            QStandardItem* item = m_chatModel->itemFromIndex(index);
            if(!item){
                continue;
            }
            item->setData(lastText,Qt::UserRole + 5);
            m_chatModel->dataChanged(index,index,{Qt::UserRole + 5});
        }
    }

    // 获取页面的QListWidget对象
    QListWidget* listWidget = page->findChild<QListWidget*>();
    if(!listWidget){
        qDebug()<<"聊天页面的列表对象获取失败";
        return;
    }

    // 判断是否需要打印一个时间标签(包括存入本地数据库和更新上一次聊天记录)
    ifAddATimeLabel(listWidget, isInit);

    // 添加一条聊天信息
    createAChatMsg(listWidget, sender, type, content, filename);
    listWidget->scrollToBottom();// 划到底部

    // 如果是程序启动的初始化，就不用插入到数据库中
    if(!isInit){
        // 将此条聊天记录存入本地数据库
        // 聊天记录表ChatData(count, friend_id, senderOrreceiver, content, type, timestamp)
        QSqlQuery query(m_db);
        query.prepare("insert into ChatData(friend_id, senderOrreceiver, content, type, filename) values(:friend_id, :senderOrreceiver, :content, :type, :filename)");
        query.bindValue(":friend_id", page->objectName());
        query.bindValue(":senderOrreceiver", (sender == m_id) ? "sender" : "receiver");
        query.bindValue(":content", content);
        query.bindValue(":type", msgType);
        query.bindValue(":filename",filename);
        if(!query.exec()){
            qDebug()<<"一条位于"<<page->objectName()<<"由"<<sender<<"发送的聊天记录存入本地数据库失败"<<query.lastError();
        }
    }
}

void Controller::createAChatMsg(QListWidget* listWidget, const QString &sender, const MsgType& type, const QString &content, QString filename)
{
    QListWidgetItem* item = new QListWidgetItem();// 创建项对象
    QWidget* itemWidget = new QWidget();// 创建一个QWidget来显示信息
    QHBoxLayout* layout = new QHBoxLayout(itemWidget);// 创建水平布局对象
    layout->setContentsMargins(0,0,0,0);// 取消边距
    layout->setAlignment(Qt::AlignCenter);

    // 创建内容标签指针（可能是文字、图片或者文件）
    QWidget* contentWidget;

    // 创建头像标签
    ChatAvatarLabel* avatarLabel = new ChatAvatarLabel();
    avatarLabel->setObjectName(sender);
    avatarLabel->setFixedSize(30,30);
    avatarLabel->setCursor(Qt::PointingHandCursor);// 设置鼠标为手掌
    avatarLabel->setObjectName(m_id);// 用于响应点击事件
    avatarLabel->setPixmap(m_info.avatarPixmap.scaled(30,30,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));
    connect(avatarLabel,&ChatAvatarLabel::chatAvatarLabelClicked,this,&Controller::onChatAvatarLabelClicked);
    if(sender != m_id){
        // 设置默认头像，防止出现好友的头像没有的情况
        QPixmap defaultPix(":/images/login/defult_avatar.png");
        avatarLabel->setPixmap(defaultPix.scaled(30,30,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));

        // 寻找朋友的头像数据
        QMap<QString, Info>::iterator it = m_friendMap.find(sender);
        if(it != m_friendMap.end()){
            Info friendInfo = it.value();
            avatarLabel->setObjectName(friendInfo.id);// 用于响应点击事件
            avatarLabel->setPixmap(friendInfo.avatarPixmap.scaled(30,30,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));
        }
    }

    // 根据类型不同添加另外的部分
    if(type == MsgType::text){
        // 设置文本标签部分
        QLabel* textLabel = new QLabel();
        textLabel->setText(content);
        textLabel->setScaledContents(true);
        textLabel->setMaximumWidth(500);// 文本宽度最大为500
        textLabel->setWordWrap(true);// 设置自动换行
        textLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);// 设置为可选
        textLabel->setStyleSheet("background-color: rgb(167, 214, 255);"
                                 "color: black; border-radius: 10px;"
                                 "padding: 5px; line-height: 2; text-align: center;"
                                 "font: 450 12pt 'Microsoft YaHei UI Light';");
        textLabel->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Minimum);
        textLabel->setContentsMargins(5,5,5,5);

        contentWidget = textLabel;
    }
    else if(type == MsgType::photo){
        // 设置图片标签部分
        PhotoLabel* photoLabel = new PhotoLabel();
        photoLabel->setFixedWidth(300);// 缩放到宽度为300，高度按比例缩放
        QPixmap pixmap;
        pixmap.loadFromData(QByteArray::fromBase64(content.toUtf8()));
        photoLabel->setPixmap(pixmap.scaled(300,300 * pixmap.height() / pixmap.width(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
        connect(photoLabel,&PhotoLabel::showAPhoto,this,&Controller::onShowAPhoto);

        contentWidget = photoLabel;
    }
    else{
        QPushButton* fileBtn = new QPushButton();
        //fileBtn->setFixedSize(200,60);
        fileBtn->setIcon(QIcon(":/images/conrtroler/file.png"));// 设置文件夹图标
        fileBtn->setIconSize(QSize(45,45));
        fileBtn->setText(filename);
        if(sender == m_id){
            fileBtn->setEnabled(false);// 自己发的不允许点击
        }
        fileBtn->setCursor(Qt::PointingHandCursor);// 设置光标样式为手
        connect(fileBtn,&QPushButton::clicked, [=](){
            emit onDownloadFile(filename, content);
        });

        contentWidget = fileBtn;
    }

    // 添加头像信息和文本
    if(sender == m_id){
        layout->addStretch();// 左边添加推力
        layout->addWidget(contentWidget);// 先添加内容信息
        layout->addWidget(avatarLabel);// 再添加头像信息
        layout->addSpacing(15);// 间距
    }
    else{
        layout->addSpacing(15);// 间距
        layout->addWidget(avatarLabel);// 先添加头像信息
        layout->addWidget(contentWidget);// 再添加内容信息
        layout->addStretch();// 右边添加推力
    }

    int height = qMax(contentWidget->sizeHint().height(), avatarLabel->sizeHint().height()) + 5;
    item->setSizeHint(QSize(listWidget->width(), height));// 设置项的大小为QWidget的大小

    // 添加到控件中
    listWidget->addItem(item);
    listWidget->setItemWidget(item, itemWidget);
}

void Controller::addATimeLabel(QListWidget *listWidget, QDateTime &time)
{
    // 计算显示的时间
    time.setTimeZone(QTimeZone("UTC"));// 设置成标准时间

    QDate currData = QDate::currentDate();// 获取今天的日期
    QDate timeData = time.date();

    QDateTime localTime = time.toTimeZone(QTimeZone::systemTimeZone());

    QString timeDisplay;// 保存最终的字符串
    // 如果是今天，只显示时间（HH:mm）
    if(timeData == currData){
        timeDisplay = "\t\t\t\t\t          ";
        timeDisplay += localTime.time().toString("HH:mm");
    }
    // 如果是昨天，显示时间（昨天 HH:mm）
    else if(timeData.addDays(1) == currData){
        timeDisplay = "\t\t\t\t\t    ";
        timeDisplay += "昨天 ";
        timeDisplay += localTime.time().toString("HH:mm");
    }
    // 如果比昨天还早，则显示年月日信息（yyyy-MM-dd HH:mm）
    else{
        timeDisplay = "\t\t\t\t\t";
        timeDisplay += localTime.toString("yyyy-MM-dd HH:mm");
    }

    // 添加进列表中
    QListWidgetItem* newItem = new QListWidgetItem();// 创建项对象
    QWidget* itemWidget = new QWidget();// 创建一个QWidget来显示信息
    QHBoxLayout* layout = new QHBoxLayout(itemWidget);// 创建水平布局对象
    layout->setContentsMargins(0,0,0,0);// 取消边距

    QLabel* timeLabel = new QLabel(itemWidget);// 时间标签
    timeLabel->setFixedSize(610, 20);
    timeLabel->setText(timeDisplay);
    layout->addWidget(timeLabel,0,Qt::AlignCenter);

    itemWidget->setLayout(layout);

    newItem->setSizeHint(itemWidget->sizeHint());
    listWidget->addItem(newItem);
    listWidget->setItemWidget(newItem, itemWidget);
}

void Controller::ifAddATimeLabel(QListWidget* listWidget, bool isInit)
{
    // 判断是否需要输出时间信息(当前是标准时间)
    bool isNeed = false;
    QDateTime currTime = QDateTime::currentDateTimeUtc();
    QString lastTimeStr = listWidget->objectName();  // 获取上一次时间字符串
    QDateTime lastTime = QDateTime::fromString(lastTimeStr,"yyyy-MM-dd HH:mm:ss");

    if(!currTime.isValid() || !lastTime.isValid()){
        qDebug()<<"判断是否需要打印时间信息的逻辑出现无效数据";
    }
    else {
        isNeed = true;
        lastTime.setTimeSpec(Qt::UTC);
        //计算时间差（单位秒），小于五分钟（300s）则不用更新时间
        qint64 secondGab = lastTime.secsTo(currTime);
        if(secondGab >= 300){
            addATimeLabel(listWidget, currTime);
        }
    }

    // 更新上一次聊天的日期（记录的是标准时间）
    listWidget->setObjectName(currTime.toString("yyyy-MM-dd HH:mm:ss"));

    // 如果是初始化，则不用将其加入数据库中
    if(!isInit){
        // 存入本地数据库（存入的是标准时间）senderOrreceiver为none
        // 聊天记录表ChatData(count, friend_id, senderOrreceiver, content, type, timestamp)
        if(isNeed){
            QSqlQuery query(m_db);
            query.prepare("insert into ChatData(friend_id, senderOrreceiver, content) values(:friend_id, :senderOrreceiver, :content)");
            query.bindValue("friend_id",listWidget->objectName());
            query.bindValue(":senderOrreceiver", "none");
            query.bindValue(":content", currTime.toString("yyyy-MM-dd HH:mm:ss"));
        }
    }
}

void Controller::updateAllTimeLabelWithDayChange()
{

}

void Controller::dealMyInfo(const QJsonObject &jsonObj)
{
    if(jsonObj["reply"].toString() == "faild"){
        qDebug()<<"获取自身的个人信息失败，后续初始化好友列表、聊天记录等无法继续进行";

    }else if(jsonObj["reply"].toString() == "succeed"){
        // 将数据存到m_info中
        m_info.id = jsonObj["id"].toString();
        m_info.pwd = jsonObj["pwd"].toString();
        m_info.nickname = jsonObj["nickname"].toString();
        m_info.gender = jsonObj["gender"].toString();
        m_info.signature = jsonObj["signature"].toString();
        m_info.question = jsonObj["question"].toString();
        m_info.answer = jsonObj["answer"].toString();


        // 将图片数据进行转换
        QPixmap avatarPix = byteArrayToPixmap(jsonObj["avatar"].toString());
        m_info.avatarPixmap = avatarPix;

        // 将主页面的头像设置为该头像
        ui->avatarLabel->setPixmap(m_info.avatarPixmap.scaled(50,50,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));

        // 将该头像保存到应用指定的目录中（防止登录窗口和主窗口的头像不一致）
        QString dirPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
        QDir dir(dirPath);
        // 确保目录存在，如果不存在则创建
        if (!dir.exists()) {
            if (!dir.mkpath(dirPath)) {
                qDebug() << "无法创建目录:" << dirPath;
                return;
            }
        }
        // 合成路径
        QString path = dirPath + QDir::separator() + "lastLoginAvatar.png";
        QImage image;
        image = avatarPix.toImage();
        if(!image.save(path,"PNG")){
            qDebug()<<"登录成功后主窗体将头像以png格式保存到本地的逻辑失败";
        }

        // 向服务器申请我的好友列表（并为每一个好友创建聊天页面）
        askForMyFriendInfo();// 放在这里是确保后续初始化不受影响
    }
}

void Controller::dealSearchFriendInfo(const QJsonObject &jsonObj)
{
    emit friendInfo(jsonObj);
}

void Controller::dealAddFriendRequest(const QJsonObject &jsonObj)
{
    // 显示一条好友申请的逻辑(往控件中添加一个项)
    QString friend_id = jsonObj["id"].toString();
    QString nickname = jsonObj["nickname"].toString();
    QPixmap avatarPix = byteArrayToPixmap(jsonObj["avatar"].toString());// 转换头像(失败会返回默认头像)

    // 判断好友申请列表中是否已经有这个好友的申请，有则直接返回
    if(m_friendRequestList.contains(friend_id)){
        return;
    }
    m_friendRequestList.append(friend_id);// 添加到列表中

    // 设置父容器和布局
    QWidget* widget = new QWidget();
    widget->setFixedSize(ui->friendListView->width(), 50);
    QHBoxLayout *layout = new QHBoxLayout();
    widget->setLayout(layout);

    // 1.设置头像
    QLabel* avatarLabel = new QLabel(widget);
    avatarLabel->setFixedSize(40,40);
    avatarLabel->setPixmap(avatarPix.scaled(40,40,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));
    layout->addWidget(avatarLabel);

    // 2.设置昵称
    QLabel* nicknameLabel = new QLabel(widget);
    nicknameLabel->setText(nickname);
    layout->addWidget(nicknameLabel);

    // 3.添加接受按钮
    QPushButton* acceptBtn = new QPushButton(widget);
    acceptBtn->setText("接受");
    layout->addWidget(acceptBtn);


    // 4.添加拒绝按钮
    QPushButton* rejectBtn = new QPushButton(widget);
    rejectBtn->setText("拒绝");
    layout->addWidget(rejectBtn);


    // 设置到控件中
    QListWidgetItem *item = new QListWidgetItem();
    ui->friendRequestistWidget->addItem(item);
    item->setSizeHint(widget->sizeHint());
    ui->friendRequestistWidget->setItemWidget(item,widget);

    // 信号连接处理
    connect(acceptBtn,&QPushButton::clicked,this,[=](){
        int row = ui->friendRequestistWidget->row(item);
        QListWidgetItem *itemTaken = ui->friendRequestistWidget->takeItem(row);
        if (itemTaken) {
            delete itemTaken; // 自动删除关联的 widget
        }

        // 从申请列表中移除
        m_friendRequestList.removeAll(friend_id);

        // 发送相关请求给服务端
        QJsonObject jsonObj;
        jsonObj["tag"] = "addFriendAnswer";
        jsonObj["reply"] = "accept";
        jsonObj["id"] = friend_id;
        sendJsonToServer(jsonObj);
    });
    connect(rejectBtn,&QPushButton::clicked,this,[=](){
        int row = ui->friendRequestistWidget->row(item);
        QListWidgetItem *itemTaken = ui->friendRequestistWidget->takeItem(row);
        if (itemTaken) {
            delete itemTaken; // 自动删除关联的 widget
        }

        // 从申请列表中移除
        m_friendRequestList.removeAll(friend_id);

        // 发送相关请求给服务端
        QJsonObject jsonObj;
        jsonObj["tag"] = "addFriendAnswer";
        jsonObj["reply"] = "reject";
        jsonObj["id"] = friend_id;
        sendJsonToServer(jsonObj);
    });


    // 判断当前是否已经在好友申请页面了，不是则设置未读
    QModelIndex index = ui->friendListView->currentIndex();
    if(ui->stackedWidget->currentIndex() != 1 || index.row() != 0){
        // 设置未读
        m_friendItem->setData(true,Qt::UserRole + 3);
        QModelIndex idx = m_friendItem->index();
        m_friendModel->dataChanged(idx,idx,{Qt::UserRole + 3});
    }
}

void Controller::dealNewFriendInfo(const QJsonObject &jsonObj)
{
    Info friend_Info;
    friend_Info.id = jsonObj["id"].toString();
    friend_Info.avatarPixmap = byteArrayToPixmap(jsonObj["avatar"].toString());
    friend_Info.gender = jsonObj["gender"].toString();
    friend_Info.nickname = jsonObj["nickname"].toString();
    friend_Info.signature = jsonObj["signature"].toString();

    // 存到好友信息映射中
    m_friendMap.insert(jsonObj["id"].toString(), friend_Info);

    // 创建这个好友的聊天项(与聊天页面)
    addAChatItem(friend_Info,true,"快来和我聊天吧");

    // 创建这个好友的好友项(与好友页面)
    addAFriendItem(friend_Info);
}

void Controller::dealYouAreDelete(QString id)
{
    // 移除当前项、好友页面、好友映射表
    QWidget* page = ui->friendInfoStackedWidget->findChild<QWidget*>(id);
    if(!page){
        qDebug()<<"无效找到并移除"<<id<<"的好友页面(脏页面)";
    }else{
        // 如果当前是选中了这个好友的
        if(ui->friendInfoStackedWidget->currentWidget() == page){
            m_friendModel->removeRow(ui->friendListView->currentIndex().row());
            // 设置成选中好友申请项
            ui->friendListView->setCurrentIndex(m_friendModel->index(0,0));
            ui->friendInfoStackedWidget->setCurrentIndex(0);
        }
        else{
            bool find = false;
            QModelIndex index;
            for(int row = 1; row < m_friendModel->rowCount(); row++){
                index = m_friendModel->index(row,0);
                if(index.data(Qt::UserRole + 4).toString() == id){
                    find = true;
                    break;
                }
            }
            if(find){
                m_friendModel->removeRow(index.row());
            }
        }
        ui->friendInfoStackedWidget->removeWidget(page);
        page->deleteLater();
    }

    m_friendMap.remove(id);// 从表移除后，将不能发送和接受信息
}

void Controller::dealMsg(const QJsonObject &jsonObj)
{
    QString sender = jsonObj["sender"].toString();
    QString type = jsonObj["type"].toString();
    QString text = jsonObj["text"].toString();
    QString filename = jsonObj["filename"].toString();

    // 判断设置类型
    MsgType msgType;
    if(type == "textType"){
        msgType = MsgType::text;
    }else if(type == "fileType"){
        msgType = MsgType::file;
    }else{
        msgType = MsgType::photo;
    }

    // 查找到对应的页面
    QWidget* page = ui->chatStackedWidget->findChild<QWidget*>(sender);
    if(!page){
        qDebug()<<"无法找到"<<sender<<"对应的聊天页面";
        return;
    }

    addAMsgIntoPage(page, msgType, sender, text, false, filename);

    // 判断当前是否正好是这个页面(不是则提示未读)
    if(ui->chatStackedWidget->currentWidget() != page){
        bool find = false;
        // 遍历
        for(int row = 0; m_chatModel->rowCount(); row++){
            QModelIndex index = m_chatModel->index(row,0);
            if(index.data(Qt::UserRole + 4).toString() == page->objectName()){
                m_chatModel->itemFromIndex(index)->setData(true, Qt::UserRole + 3);
                m_chatModel->dataChanged(index,index,{Qt::UserRole + 3});
                liftSomeoneInChatView(page->objectName());
                find = true;
                break;
            }
        }

        // 没有找的的话则创建一个这个项(聊天页面是一定有的)
        if(!find){
            QMap<QString,Info>::iterator it = m_friendMap.find(page->objectName());
            if(it != m_friendMap.end()){
                Info info = it.value();
                QStandardItem* item = new QStandardItem();
                item->setData(info.avatarPixmap,Qt::UserRole + 1);// 添加头像
                item->setData(info.nickname,Qt::UserRole + 2);// 添加昵称
                item->setData(true,Qt::UserRole + 3);// 添加未读标志
                item->setData(info.id,Qt::UserRole + 4);// 添加账号信息
                item->setData(text,Qt::UserRole + 5);// 添加上一次聊天信息
                m_chatModel->appendRow(item);
                liftSomeoneInChatView(info.id);// 提升这个项
            }
        }
    }
}

void Controller::dealFriendCancel(QString friend_id)
{
    // 从好友映射中移除
    if(m_friendMap.contains(friend_id)){
        m_friendMap.remove(friend_id);
    }
}

void Controller::dealDeleteAccount(const QJsonObject &jsonObj)
{
    if(jsonObj["reply"].toString() == "faild"){
        QMessageBox::warning(this,"警告","暂时无法注销账号");
    }
    else if(jsonObj["reply"].toString() == "succeed"){
        QMessageBox::warning(this,"提示","注销成功，期待和你的再次相遇");
        if(m_db.isOpen()){
            m_db.close();
        }
        // 删除掉本地数据库文件,(文件名为m_id + '.db')
        QString appDir = QCoreApplication::applicationDirPath();
        QString filePath = appDir + "/" + m_id + ".db";
        QFile::remove(filePath);

        // 打开登录窗口
        emit goBackToLogin();// 提醒appManager切换回登录窗口
    }
}

void Controller::dealUpdateAFriendInfo(const QJsonObject &jsonObj)
{
    // 确保好友列表中有这个好友
    if(!m_friendMap.contains(jsonObj["id"].toString())){
        return;
    }
    QString id = jsonObj["id"].toString();
    QString nickname = jsonObj["nickname"].toString();
    QString signature = jsonObj["signature"].toString();
    QString gender = jsonObj["gender"].toString();
    QString avatar = jsonObj["avatar"].toString();

    Info info;
    info.id = id;
    info.nickname = nickname;
    info.signature = signature;
    info.gender = gender;

    QByteArray byte = QByteArray::fromBase64(avatar.toUtf8());
    QPixmap pix;
    pix.loadFromData(byte);
    if(pix.isNull()){
        info.avatarPixmap = m_friendMap[id].avatarPixmap;
    }else{
        info.avatarPixmap = pix;
    }

    m_friendMap[id] = info;// 更新info的值

    addAFriendPage(info);// 更新好友页面
}

void Controller::dealFriendInfo(const QJsonObject &jsonObj)
{
    if(jsonObj["reply"].toString() == "faild"){
        QMessageBox::warning(this,"警告","无法获取您的好友列表，请退出后重试");
        this->close();// 关闭当前窗口
    }
    else if(jsonObj["reply"].toString() == "succeed"){
        // 取出每一个好友的信息，并存储到映射表中
        QJsonArray jsonArray = jsonObj["array"].toVariant().toJsonArray();
        for(const QJsonValue& value : jsonArray){
            const QJsonObject& js = value.toObject();
            Info friendInfo;
            friendInfo.id = js["id"].toString();
            friendInfo.gender = js["gender"].toString();
            friendInfo.avatarPixmap = byteArrayToPixmap(js["avatar"].toString());
            friendInfo.nickname = js["nickname"].toString();
            friendInfo.signature = js["signature"].toString();

            m_friendMap.insert(js["id"].toString(),friendInfo);

            addAFriendItem(friendInfo);
            addAChatPage(js["id"].toString());// 添加聊天页面
        }

        // 通过本地数据库，初始化聊天记录列表
        initChatData();// 放在这里是确保在所有页面创建完后再开始
        // 通过本地数据库，初始化聊天项
        initChatItem();// 放在这里是确保有好友映射后才进行
        // 向服务器申请我的好友申请列表信息
        askForMyFriendRequestList();// 放在这里仅仅是为了在完成好友映射后进行
        askForMyUnReadMsg();// 放在这里仅仅是为了在完成好友映射后进行
    }
}

void Controller::dealFriendRequestList(const QJsonObject &jsonObj)
{
    if(jsonObj["reply"].toString() == "faild"){
        QMessageBox::warning(this,"警告","无法获取您的好友申请列表，请退出后重试");
        this->close();// 关闭当前窗口
    }
    else if(jsonObj["reply"].toString() == "succeed"){
        // 取出每一个好友的信息，并存储到映射表中
        QJsonArray jsonArray = jsonObj["array"].toVariant().toJsonArray();
        for(const QJsonValue& value : jsonArray){
            const QJsonObject& js = value.toObject();
            // 调用添加好友申请的逻辑函数
            dealAddFriendRequest(js);
        }
    }
}

void Controller::dealMyUnReadMsg(const QJsonObject &jsonObj)
{
    if(jsonObj["reply"].toString() == "faild"){
        QMessageBox::warning(this,"警告","无法获取您的未读消息列表，请退出后重试");
        this->close();// 关闭当前窗口
    }
    else if(jsonObj["reply"].toString() == "succeed"){
        // 取出每一个未读消息
        QJsonArray jsonArray = jsonObj["array"].toVariant().toJsonArray();
        for(const QJsonValue& value : jsonArray){
            const QJsonObject& js = value.toObject();
            // 调用添加好友申请的逻辑函数
            QString friend_id = js["friend_id"].toString();
            QString content = js["content"].toString();
            QString filename = js["filename"].toString();
            QString msgType = js["message_type"].toString();
            MsgType type;
            if(msgType == "textType"){
                type = MsgType::text;
            }else if(msgType == "photoType"){
                type = MsgType::photo;
            }else{
                type = MsgType::file;
            }

            // 将其加入聊天页面
            QWidget* page = ui->chatStackedWidget->findChild<QWidget*>(friend_id);
            if(!page){
                continue;
            }
            addAMsgIntoPage(page,type,friend_id,content,false,filename);

            // 如果有聊天项，则将其更新聊天项中（上一次聊天记录，提升该项）
            for(int row = 0; row < m_chatModel->rowCount(); row++){
                QModelIndex index = m_chatModel->index(row,0);
                if(index.data(Qt::UserRole + 4).toString() == friend_id){
                    QStandardItem* item = m_chatModel->itemFromIndex(index);
                    if(item){
                        item->setData(true, Qt::UserRole + 3);
                        m_chatModel->dataChanged(index,index,{Qt::UserRole + 3});
                        liftSomeoneInChatView(friend_id);
                    }
                    break;
                }
            }
        }
    }
}

void Controller::onDisconnected()
{
    // 提醒说网络断开，重新登录
    QMessageBox::warning(this,"警告","网络连接中断，请重新登录");

    // 发送信号，回到登录页面
    emit goBackToLogin();
}

void Controller::onTextMessageReceived(const QString &message)
{
    // 检查收到的数据是不是json格式
    QJsonDocument jsonDoc = QJsonDocument::fromJson(message.toUtf8());
    if(!jsonDoc.isObject()){
        qDebug()<<"客户端收到一条非法数据";
        return;
    }

    // 转为json对象
    QJsonObject jsonObj = jsonDoc.object();
    if(jsonObj["end"] != "end"){
        qDebug()<<"客户端收到一条没有结束标志的非法数据";
        return;
    }

    //根据json["tag"]标签进行分类处理
    QString tag = jsonObj["tag"].toString();

    if(tag == "myInfo"){
        dealMyInfo(jsonObj);
    }
    else if(tag == "msg"){
        dealMsg(jsonObj);
    }
    else if(tag == "searchFriendInfo"){
        dealSearchFriendInfo(jsonObj);
    }
    else if(tag == "addFriendRequest"){
        dealAddFriendRequest(jsonObj);
    }
    else if(tag == "newFriendInfo"){
        dealNewFriendInfo(jsonObj);
    }
    else if(tag == "youAreDelete"){
        dealYouAreDelete(jsonObj["id"].toString());
    }
    else if(tag == "friendInfo"){
        dealFriendInfo(jsonObj);
    }
    else if(tag == "friendRequestList"){
        dealFriendRequestList(jsonObj);
    }
    else if(tag == "myUnReadMsg"){
        dealMyUnReadMsg(jsonObj);
    }
    else if(tag == "friend_cancel"){
        dealFriendCancel(jsonObj["friend_id"].toString());
    }
    else if(tag == "deleteAccount"){
        dealDeleteAccount(jsonObj);
    }
    else if(tag == "updateAFriendInfo"){
        dealUpdateAFriendInfo(jsonObj);
    }
}

void Controller::onAskForFriendInfo(QString id)
{
    // 先判断是否已经是自己的好友了
    if(m_friendMap.contains(id)){
        QJsonObject jsonObj;
        jsonObj["reply"] = "repeat";
        emit friendInfo(jsonObj);
        return;
    }

    // 向服务端发送请求
    QJsonObject jsonObj;
    jsonObj["tag"] = "searchFriendInfo";
    jsonObj["id"] = id;
    sendJsonToServer(jsonObj);
}

void Controller::onAddFriendRequest(QString id)
{
    QJsonObject jsonObj;
    jsonObj["tag"] = "addFriendRequest";
    jsonObj["id"] = id;
    sendJsonToServer(jsonObj);
}

void Controller::onFriendListViewIndexChange(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous);
    if(current.row() == 0){
        m_friendItem->setData(false,Qt::UserRole + 3);
        m_friendModel->dataChanged(current,current,{Qt::UserRole + 3});
        ui->friendInfoStackedWidget->setCurrentIndex(1);
        ui->nameFriendLabel->setText("");
    }else {
        QString id = current.data(Qt::UserRole + 4).toString();
        QWidget* page = ui->friendInfoStackedWidget->findChild<QWidget*>(id);
        if(page){
            ui->friendInfoStackedWidget->setCurrentWidget(page);
            // 将上方的名字label变成对应的名称
            ui->nameFriendLabel->setText(current.data(Qt::UserRole + 2).toString());
        }
        else{
            qDebug()<<"在切换到"<<id<<"对应的好友页面时无法找到！";
            ui->friendInfoStackedWidget->setCurrentIndex(0);// 显示空白页
            ui->nameFriendLabel->setText("");
        }
    }
}

void Controller::onDeleteAFriend(QString id)
{
    // 移除当前项、好友页面、好友映射表
    m_friendModel->removeRow(ui->friendListView->currentIndex().row());
    QWidget* page = ui->friendInfoStackedWidget->findChild<QWidget*>(id);
    if(!page){
        qDebug()<<"无效找到并移除"<<id<<"的好友页面";
    }else{
        ui->friendInfoStackedWidget->removeWidget(page);
        page->deleteLater();
    }

    m_friendMap.remove(id);// 从表移除后，将不能发送和接受信息

    // 设置成选中好友申请项
    ui->friendListView->setCurrentIndex(m_friendModel->index(0,0));
    ui->friendInfoStackedWidget->setCurrentIndex(0);

    // 通知服务端，我已经将其删除了
    QJsonObject jsonObj;
    jsonObj["tag"] = "deleteAFriend";
    jsonObj["friend_id"] = id;
    sendJsonToServer(jsonObj);
}

void Controller::onChatListViewIndexChange(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous);
    // 选中对应的聊天页面
    QString id = current.data(Qt::UserRole + 4).toString();

    // 遍历ui->chatStackedWidget容器，寻找某一页的objectname是当前
    QWidget* page = ui->chatStackedWidget->findChild<QWidget*>(id);
    if(page){
        ui->chatStackedWidget->setCurrentWidget(page);
        // 将上方的名字label变成对应的名称
        ui->nameChatLabel->setText(current.data(Qt::UserRole + 2).toString());
    }
    else{
        qDebug()<<"在切换到"<<id<<"对应的聊天页面时无法找到！";
        ui->chatStackedWidget->setCurrentIndex(0);// 显示空白页
        ui->nameChatLabel->setText("");
    }

    // 提升
    liftSomeoneInChatView(id);

    // 检查是否需要消除未读提示
    if(current.data(Qt::UserRole + 3).toBool() == true){
        QStandardItem* item = m_chatModel->itemFromIndex(current);
        item->setData(false, Qt::UserRole + 3);
        m_chatModel->dataChanged(current,current,{Qt::UserRole + 3});
    }
}

void Controller::onChatAvatarLabelClicked(QString id)
{
    // 如果是自己的，则打开我的页面
    if(id == m_id){
        ui->meBtn->click();
    }
    // 如果是好友的，则打开好友的队友的页面
    else{
        // 遍历找出属于哪一个好友项
        for(int row = 0; row < m_friendModel->rowCount(); row++){
            QModelIndex index = m_friendModel->index(row,0);
            if(index.data(Qt::UserRole + 4) == id){
                ui->friendListView->setCurrentIndex(index);// 将其设置为选中项
                changeButtonImage(ui->friendBtn);
                break;
            }
        }
    }
}

void Controller::onShowAPhoto(QPixmap pixmap)
{
    PhotoViewer* photoViewer = new PhotoViewer(pixmap);
    photoViewer->show();
}

void Controller::onDownloadFile(QString filename, QString content)
{
    // 打开一个对话框，选择路径
    QString savePath = QFileDialog::getSaveFileName(this,tr("保存文件"),filename,tr("所有文件 (*)"));
    if(savePath.isEmpty() || savePath == filename){
        return;
    }

    // 读取文件内容
    QByteArray fileData = QByteArray::fromBase64(content.toUtf8());
    if (fileData.isEmpty() && !content.isEmpty()) {
        QMessageBox::warning(this, tr("文件数据错误"), tr("无效的文件数据"));
        return;
    }

    // 创建文件对象
    QFile file(savePath);
    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::warning(this, tr("保存文件失败"), tr("无法保存文件到指定位置"));
        return;
    }

    qint64 bytesWritten = file.write(fileData);
    // 将文件数据写入文件
    if (bytesWritten != fileData.size()) {
        QMessageBox::warning(this, tr("保存文件失败"), tr("写入文件失败"));
        return;
    }
    file.close();

    // 提示用户文件保存成功
    QMessageBox::information(this, tr("提示"), tr("文件保存完成"));
}

void Controller::onMenuChoice(QModelIndex index)
{
    if (!index.isValid()) {
        return;
    }

    // 在本地数据库中删除这个项
    // 创建聊天项表ChatItem(count, friend_id, lastMsg, timestamp)
    QSqlQuery query(m_db);
    query.prepare("delete from ChatItem where friend_id = :friend_id");
    query.bindValue(":friend_id",index.data(Qt::UserRole + 4).toString());
    if(!query.exec()){
        qDebug()<<"从数据库移除一个聊天项失败（脏数据）";
    }

    // 移除这个会话
    if(!m_chatModel->removeRow(index.row(),index.parent())){
        qDebug()<<"移除失败";
    }
    ui->chatStackedWidget->setCurrentIndex(0);
    ui->nameChatLabel->setText("");
}

void Controller::on_chatBtn_clicked()
{
    // 切换显示的界面
    changeButtonImage(ui->chatBtn);
}


void Controller::on_friendBtn_clicked()
{
    // 切换显示的界面
    changeButtonImage(ui->friendBtn);
}


void Controller::on_meBtn_clicked()
{
    // 设置我的页面中的值
    ui->idLineEdit->setText(m_info.id);
    ui->pwdLineEdit->setText(m_info.pwd);
    if(m_info.gender == "男"){
        ui->nanRadioButton->setChecked(true);
    }else{
        ui->nvRadioButton->setChecked(true);
    }
    ui->nicknameLineEdit->setText(m_info.nickname);
    ui->questionTextEdit->setText(m_info.question);
    ui->answerTextEdit->setText(m_info.answer);
    ui->signaturePlainTextEdit->setPlainText(m_info.signature);
    ui->bigAvatarLabel->setPixmap(m_info.avatarPixmap.scaled(200,200,Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation));

    // 初始时未点击修改按钮，这些都不允许修改
    setMyPageEnable(false);

    // 切换显示的界面
    changeButtonImage(ui->meBtn);
}


void Controller::on_settingBtn_clicked()
{
    // 切换显示的界面
    changeButtonImage(ui->settingBtn);
}


void Controller::on_exitAccountBtn_clicked()
{
    // 提醒服务端，自己已经退出登录
    QJsonObject jsonObj;
    jsonObj["tag"] = "outOfLogin";
    sendJsonToServer(jsonObj);

    // 延迟200毫秒，保证服务端有时间处理
    QTimer::singleShot(200,[=](){
        emit goBackToLogin();// 提醒appManager切换回登录窗口
    });
}


void Controller::on_deleteAccountBtn_clicked()
{
    // 向服务端发送请求，要求注销账号
    QJsonObject jsonObj;
    jsonObj["tag"] = "deleteAccount";
    sendJsonToServer(jsonObj);
}


void Controller::on_addFriendBtn_clicked()
{
    // 弹出添加好友窗口
    AddFriend* add = new AddFriend(m_id, this);

    // 连接信号和槽，发送添加申请/查找申请
    connect(add,&AddFriend::askForFriendInfo,this,&Controller::onAskForFriendInfo);
    connect(add,&AddFriend::addFriendRequest,this,&Controller::onAddFriendRequest);
    connect(this,&Controller::friendInfo,add,&AddFriend::onFriendInfo);

    add->exec();

    // 断开信号和槽连接
    disconnect(add,&AddFriend::askForFriendInfo,this,onAskForFriendInfo);
    disconnect(add,&AddFriend::addFriendRequest,this,onAddFriendRequest);
    disconnect(this,&Controller::friendInfo,add,&AddFriend::onFriendInfo);

    add->deleteLater();
}


void Controller::on_sendBtn_clicked()
{
    QString text = ui->msgTextEdit->toPlainText();
    // 判断是否是空信息（不处理）
    if(text.isEmpty()){
        return;
    }

    // 尝试获取当前聊天页面的page对象
    QWidget* page = ui->chatStackedWidget->currentWidget();
    if(!page){
        qDebug()<<"无法获取当前聊天页面的page对象";
        return;
    }

    // 判断对方是否还是自己的好友（可能被删了）
    if(!m_friendMap.contains(page->objectName())){
        QMessageBox::warning(this,"警告","对方将你删除或已注销账号！");
        return;
    }

    addAMsgIntoPage(page, MsgType::text, m_id, text, false);

    // 发送这条聊天信息到服务端
    QJsonObject jsonObj;
    jsonObj["tag"] = "msg";
    jsonObj["receiver"] = page->objectName();// 接收方
    jsonObj["text"] = text;
    jsonObj["type"] = "textType";
    sendJsonToServer(jsonObj);

    ui->msgTextEdit->clear();
}

void Controller::closeEvent(QCloseEvent *event)
{
    // 更新本地数据库聊天项表的删一次聊天记录中
    // 聊天项表ChatItem(count, friend_id, lastMsg, timestamp)
    QSqlQuery query(m_db);
    query.prepare("update ChatItem set lastMsg = :lastMsg where friend_id = :friend_id");
    for(int row = 0; row < m_chatModel->rowCount(); row++){
        QModelIndex index = m_chatModel->index(row,0);
        QString lastStr = index.data(Qt::UserRole + 5).toString();
        QString friend_id = index.data(Qt::UserRole + 4).toString();
        query.bindValue(":lastMsg",lastStr);
        query.bindValue(":friend_id",friend_id);
        if(!query.exec()){
            qDebug()<<"程序结束更新上一次聊天记录的sql语句执行失败"<<query.lastError();
        }
    }

    // 接受聊天记录
    event->accept();
}


void Controller::on_imageBtn_clicked()
{
    // 尝试获取当前聊天页面的page对象
    QWidget* page = ui->chatStackedWidget->currentWidget();
    if(!page){
        qDebug()<<"无法获取当前聊天页面的page对象";
        return;
    }

    // 判断对方是否还是自己的好友（可能被删了）
    if(!m_friendMap.contains(page->objectName())){
        QMessageBox::warning(this,"警告","对方将你删除或已注销账号！");
        return;
    }

    // 打开图片选择框，选择一张图片
    QString pixmapPath = QFileDialog::getOpenFileName(this, tr("选择头像"),QDir::homePath(),tr("Images (*.png *.bmp *.jpeg *.jpg)"));
    if(pixmapPath.isEmpty()){
        return;
    }

    QPixmap pix;
    if(!pix.load(pixmapPath)){
        QMessageBox::warning(this,"警告","您选择的图片有误或无效",QMessageBox::Ok);
        return;
    }

    QByteArray pixmapData;
    QBuffer buffer(&pixmapData);
    buffer.open(QIODevice::WriteOnly);
    if(!pix.save(&buffer, "PNG")){
        QMessageBox::warning(this,"警告","您选择的图片有误或无效",QMessageBox::Ok);
        return;
    }

    QString pixmapStr = pixmapData.toBase64();// 转换为 Base64 编码的字符串

    addAMsgIntoPage(page, MsgType::photo, m_id, pixmapStr, false);

    // 发送这条聊天信息到服务端
    QJsonObject jsonObj;
    jsonObj["tag"] = "msg";
    jsonObj["receiver"] = page->objectName();// 接收方
    jsonObj["text"] = pixmapStr;
    jsonObj["type"] = "photoType";
    sendJsonToServer(jsonObj);
}


void Controller::on_fileBtn_clicked()
{
    // 尝试获取当前聊天页面的page对象
    QWidget* page = ui->chatStackedWidget->currentWidget();
    if(!page){
        qDebug()<<"无法获取当前聊天页面的page对象";
        return;
    }

    // 判断对方是否还是自己的好友（可能被删了）
    if(!m_friendMap.contains(page->objectName())){
        QMessageBox::warning(this,"警告","对方将你删除或已注销账号！");
        return;
    }

    // 弹出对话框选择文件
    QString filePath = QFileDialog::getOpenFileName(this, tr("选择要发送的文件"), QString(), tr("所有文件 (*)"));
    if (filePath.isEmpty()) {
        return;
    }

    // 检查文件是否有效或过大
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)){
        QMessageBox::warning(this,"错误","选择的文件无效");
        return;
    }
    qint64 fileSize = file.size();
    const qint64 maxFileSize = 256 * 1024 * 1024; // 256M
    if (fileSize > maxFileSize) {
        QMessageBox::warning(this,"错误","发送的文件不能超过256MB");
        return;
    }

    // 提取文件名
    QFileInfo fileInfo(filePath);// 创建 QFileInfo 对象
    QString filename =  fileInfo.fileName();// 获取文件名

    // 将文件转为字节数组字符串
    QByteArray fileData = file.readAll();
    file.close();
    QString fileStr = fileData.toBase64();

    addAMsgIntoPage(page, MsgType::file, m_id, fileStr, false, filename);

    // 发送这条聊天信息到服务端
    QJsonObject jsonObj;
    jsonObj["tag"] = "msg";
    jsonObj["receiver"] = page->objectName();// 接收方
    jsonObj["text"] = fileStr;
    jsonObj["type"] = "fileType";
    jsonObj["filename"] = filename;
    sendJsonToServer(jsonObj);
}


void Controller::on_editSavsBtn_clicked()
{
    if(ui->editSavsBtn->text() == "修改"){
        ui->editSavsBtn->setText("保存");
        setMyPageEnable(true);// 允许修改个人信息
    }
    else{
        ui->editSavsBtn->setText("修改");
        setMyPageEnable(false);
        QString pwd = ui->pwdLineEdit->text();
        QString nickname = ui->nicknameLineEdit->text();
        QString gender = ui->nanRadioButton->isChecked() ? "男" : "女";
        QString signature = ui->signaturePlainTextEdit->toPlainText();
        QString question = ui->questionTextEdit->toPlainText();
        QString answer = ui->answerTextEdit->toPlainText();
        QPixmap pixmap = ui->bigAvatarLabel->pixmap();

        // 判断是否做出修改
        if(pwd != m_info.pwd || nickname != m_info.nickname || gender != m_info.gender ||
            signature != m_info.signature || question != m_info.question ||
            answer != m_info.answer || pixmap.toImage() != m_info.avatarPixmap.toImage()){
            QJsonObject jsonObj;
            jsonObj["tag"] = "updateMyInfo";
            jsonObj["pwd"] = pwd;
            jsonObj["nickname"] = nickname;
            jsonObj["gender"] = gender;
            jsonObj["signature"] = signature;
            jsonObj["question"] = question;
            jsonObj["answer"] = answer;

            if(pixmap.toImage() != m_info.avatarPixmap.toImage()){
                QByteArray byteArray;
                QBuffer buffer(&byteArray);
                buffer.open(QBuffer::WriteOnly);
                if(!pixmap.save(&buffer, "PNG")){
                    QMessageBox::warning(this,"警告","您选择的图片有误或无效",QMessageBox::Ok);
                    ui->bigAvatarLabel->setPixmap(m_info.avatarPixmap);
                    return;
                }
                QString avatarStr = byteArray.toBase64();
                jsonObj["avatar"] = avatarStr;
            }
            sendJsonToServer(jsonObj);
        }
    }
}

